package com.tom.architect02.ui30.day22;

import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;

import androidx.annotation.Nullable;

/**
 * Added by Tom on 2024/06/20.
 */
public class ListDataScreenView extends LinearLayout implements View.OnClickListener {
    private Context mContext;
    // 1.1 创建头部用来存放 Tab
    private LinearLayout mMenuTabView;
    // 1.2 创建 FrameLayout 用来存放 = 阴影（View） + 菜单内容布局(FrameLayout)
    private FrameLayout mMenuMiddleView;
    // 阴影
    private View mShadowView;
    // 创建菜单用来存放菜单内容
    private FrameLayout mMenuContainerView;
    // 阴影的颜色
    private int mShadowColor = 0x88888888;
    // 筛选菜单的 Adapter
    private BaseMenuAdapter mAdapter;
    // 内容菜单的高度
    private int mMenuContainerHeight;
    // 当前打开的位置
    private int mCurrentPosition = -1;
    private long DURATION_TIME = 350;
    // 动画是否 正在执行
    private boolean mAnimatorExecute;

    //region 构造函数
    public ListDataScreenView(Context context) {
        this(context, null);
    }

    public ListDataScreenView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ListDataScreenView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        initLayout();
    }
    //endregion

    //region 初始化布局，测量宽高
    private void initLayout() {
        //  1. 先创建一个 xml 布局 ，再加载，findViewById
        //  2. 简单的效果用代码去创建  早期IOS 用代码创建布局
        setOrientation(VERTICAL); // 整体垂直布局
        // 1.1 创建头部用来存放 Tab
        mMenuTabView = new LinearLayout(mContext);
        mMenuTabView.setBackgroundColor(Color.GREEN);
        mMenuTabView.setLayoutParams(new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        addView(mMenuTabView);

        // 1.2 创建 FrameLayout 用来存放 = 阴影（View）+ 菜单内容布局(FrameLayout)
        mMenuMiddleView = new FrameLayout(mContext);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, 0);
        params.weight = 1; // 除了tab的高度，菜单栏覆盖全屏高度。
        mMenuMiddleView.setLayoutParams(params);
        addView(mMenuMiddleView);

        // 1.2.1 创建阴影， 可以不用设置 LayoutParams 默认就是 MATCH_PARENT/MATCH_PARENT
        mShadowView = new View(mContext);
        mShadowView.setBackgroundColor(mShadowColor);
        mShadowView.setAlpha(0f); // 默认透明度0，不显示阴影
        mShadowView.setOnClickListener(this); // 阴影点击，关闭菜单。
        mShadowView.setVisibility(GONE);
        mMenuMiddleView.addView(mShadowView);
        // 1.2.2 创建菜单，用来存放菜单内容
        mMenuContainerView = new FrameLayout(mContext);
        mMenuContainerView.setBackgroundColor(Color.WHITE);
        mMenuMiddleView.addView(mMenuContainerView);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.e("TAG", "onMeasure");
        int height = MeasureSpec.getSize(heightMeasureSpec);

        // 避免onMeasure执行多次，setTranslationY，将菜单隐藏。
        if (mMenuContainerHeight == 0 && height > 0) {
            // 内容的高度应该不是全部  应该是整个 View的 75%
            mMenuContainerHeight = (int) (height * 0.75f);
            ViewGroup.LayoutParams params = mMenuContainerView.getLayoutParams();
            params.height = mMenuContainerHeight;
            mMenuContainerView.setLayoutParams(params);
            // 进来的时候阴影不显示 ，默认内容也是不显示的（把它移上去）
            mMenuContainerView.setTranslationY(-mMenuContainerHeight);
        }
    }
    //endregion

    // 具体的观察者，实现类
    private class AdapterMenuObserver extends MenuObserver {
        @Override
        public void closeMenu() {
            // 有订阅了，就会收到通知。 关闭菜单。
            ListDataScreenView.this.closeMenu();
        }
    }
    private AdapterMenuObserver mMenuObserver; // 具体观察者对象

    /**
     * 设置 Adapter
     *
     * @param adapter
     */
    public void setAdapter(BaseMenuAdapter adapter) {
        if (adapter == null) throw new RuntimeException("adapter is null!");
        // 观察者：微信的公众号用户
        if (mAdapter != null && mMenuObserver != null) {
            // 取消订阅，避免多次setAdapter
            mAdapter.unregisterDataSetObserver(mMenuObserver);
        }
        this.mAdapter = adapter;
        // 注册观察者：具体的观察者实例对象： 订阅
        mMenuObserver = new AdapterMenuObserver();
        mAdapter.registerDataSetObserver(mMenuObserver);

        // 获取有多少条
        int count = mAdapter.getCount();
        for (int i = 0; i < count; i++) {
            // 获取菜单的Tab
            View tabView = mAdapter.getTabView(i, mMenuTabView);
            mMenuTabView.addView(tabView);
            LinearLayout.LayoutParams params = (LayoutParams) tabView.getLayoutParams();
            params.weight = 1; // 菜单宽度设置相等
            tabView.setLayoutParams(params);

            // 设置tab点击事件
            setTabClick(tabView, i);
            // 获取菜单的内容 mMenuContainerView是一个FrameLayout。
            View menuView = mAdapter.getMenuView(i, mMenuContainerView);
            menuView.setVisibility(GONE); // 菜单内容默认不显示
            mMenuContainerView.addView(menuView);

            if (i == 1) {
                tabView.performClick(); // 默认选中
            }
        }
        // 挤到一堆去了 ，菜单的 Tab 不见了(解决) ，宽度不是等宽，weight要是为1
        // 内容的高度应该不是全部  应该是整个 View 高度的 75%
        // 进来的时候阴影不显示 ，内容也是不显示的（把它移上去）
        // 内容还没有显示出来,打开的时候显示当前位置的菜单，关闭的时候隐藏，阴影点击应该要关闭菜单
        // 动画在执行的情况下就不要在响应动画事件
        // 打开和关闭 变化tab的显示 ， 肯定不能把代码写到 ListDataScreen 里面来
        // 当菜单是打开的状态 不要执行动画只要切换


    }

    /**
     * 设置tab的点击
     *
     * @param tabView
     * @param position
     */
    private void setTabClick(View tabView, int position) {
        tabView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mCurrentPosition == -1) {
                    // 没打开，去打开position 的菜单：执行动画
                    openMenu(position, tabView);
                } else {
                    if (mCurrentPosition == position) {
                        // 打开了, 去关闭菜单：执行动画
                        closeMenu();
                    } else {
                        // 菜单是打开状态，不执行动画，只切换tab显示。
                        // 切换一下显示：关闭之前的菜单，打开新选择的菜单。切换tab，不重新执行动画。
                        View currentMenu = mMenuContainerView.getChildAt(mCurrentPosition);
                        currentMenu.setVisibility(View.GONE);
                        mAdapter.menuClose(mMenuTabView.getChildAt(mCurrentPosition)); // 修改tab选中状态

                        // 更新 打开的菜单位置
                        mCurrentPosition = position;
                        currentMenu = mMenuContainerView.getChildAt(mCurrentPosition);
                        currentMenu.setVisibility(View.VISIBLE);
                        mAdapter.menuOpen(mMenuTabView.getChildAt(mCurrentPosition)); //  修改tab选中状态
                    }
                }
            }
        });
    }


    //region 打开、关闭菜单
    // 关闭菜单
    public void closeMenu() {
        // 正在执行动画中。不要再相应开关菜单事件。
        if (mAnimatorExecute) return;

        // 关闭动画  位移动画  透明度动画
        ObjectAnimator translationAnimator = ObjectAnimator.ofFloat(mMenuContainerView, "translationY", 0, -mMenuContainerHeight);
        translationAnimator.setDuration(DURATION_TIME);
        translationAnimator.start();
        mShadowView.setVisibility(View.VISIBLE);
        ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(mShadowView, "alpha", 1f, 0f);
        alphaAnimator.setDuration(DURATION_TIME);
        // 要等关闭动画执行完才能去隐藏当前菜单
        alphaAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                View menuView = mMenuContainerView.getChildAt(mCurrentPosition);
                menuView.setVisibility(View.GONE); // 关闭菜单结束，隐藏已打开的菜单。
                mCurrentPosition = -1;
                mShadowView.setVisibility(GONE); // 去掉阴影。
                mAnimatorExecute = false;
            }

            @Override
            public void onAnimationStart(Animator animation) {
                mAnimatorExecute = true;
                mAdapter.menuClose(mMenuTabView.getChildAt(mCurrentPosition)); // 恢复tab的样式
            }
        });
        alphaAnimator.start(); // start放到最后，避免onAnimationStart 执行不到。
    }

    // 打开菜单
    private void openMenu(final int position, final View tabView) {
        if (mAnimatorExecute) return;

        mShadowView.setVisibility(View.VISIBLE);
        // 获取当前位置显示当前菜单，菜单是加到了菜单容器
        View menuView = mMenuContainerView.getChildAt(position);
        menuView.setVisibility(View.VISIBLE);

        // 打开开启动画  位移动画  透明度动画
        ObjectAnimator translationAnimator = ObjectAnimator.ofFloat(mMenuContainerView, "translationY", -mMenuContainerHeight, 0);
        translationAnimator.setDuration(DURATION_TIME);
        translationAnimator.start();
        ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(mShadowView, "alpha", 0f, 1f);
        alphaAnimator.setDuration(DURATION_TIME);

        alphaAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mAnimatorExecute = false;
                mCurrentPosition = position; // 更新当前代开的菜单
            }

            @Override
            public void onAnimationStart(Animator animation) {
                mAnimatorExecute = true;
                // 把当前的 tab 传到外面
                mAdapter.menuOpen(tabView); // 相关tab的样式 为选中状态。
            }
        });
        alphaAnimator.start();
    }

    @Override
    public void onClick(View v) {
        closeMenu(); // 点击mShadowView 阴影，关闭菜单
    }
    //endregion

}
